import pymel.core as pm

class Reference(object):

    def __init__(self, refNodes=None , renderLayers=None , baseName=""):
        if refNodes is None:
            refNodes = self.getReferenceNodes()

        self.renderLayers = renderLayers
        self.baseName = baseName
        self.referenceNodes = refNodes
        self.fileRefs = self.getFileReferences()

    def getReferenceNodes(self):
        refs = pm.ls(type="reference")

        #sharedReferenceNode = ""

        #for ref in refs:
            #if ref == "sharedReferenceNode":
                #sharedReferenceNode = ref

        #if sharedReferenceNode is not "":
            #refs.remove(sharedReferenceNode)

        return refs

    def getFileReferences(self):
        fileRefs = []
        for ref in self.referenceNodes:
            fileRefs.append( pm.FileReference( refnode = ref ) )
        return fileRefs

    def createRenderLayer(self, renderLayer):#, nodes = None):
        #pm.select(nodes)
        renderLayerObject = pm.createRenderLayer( n = renderLayer, noRecurse = True)
        #assert ( isinstance(renderLayerObject,pm.RenderLayer))
        return renderLayerObject

    def autoCreateRenderLayers(self):
        for fileRef in self.fileRefs:
            self.createRenderLayers( fileRef, self.renderLayers, self.baseName )

    def getCleanLayerName (self, rawLayerName):
        splits = rawLayerName.split('#')
        return splits[0]

    def createRenderLayers(self, fileRef, renderLayers, baseName = ""):
        assert( isinstance(fileRef,pm.FileReference))

        renderLayerNodes = []

        isLoaded = fileRef.isLoaded()

        if not isLoaded:
            fileRef.load()

        allNodes = fileRef.nodes()

        # change render settings to specified flag
        miDefaultOptions = pm.PyNode('miDefaultOptions')    

        for renderLayer in renderLayers:
            # get the renderLayerName
            if baseName is not "":
                renderLayerName = baseName + "_" + self.getCleanLayerName( renderLayer )
            else :
                renderLayerName = self.getCleanLayerName( renderLayer )

            # create renderLayer
            renderLayerNode = None
            renderLayerNode = self.createRenderLayer( renderLayerName)#, allNodes )

            # parse the layer settings
            layerSettings = self.parseLayerSettings( renderLayer )
            noSettings = False

            if len(layerSettings) != 0:
                primaryVisibility = int(layerSettings["pv"])
                finalGather = int(layerSettings["fg"])
                motionBlur = int(layerSettings["mb"])
                furRender = int(layerSettings["fur"])
            else:
                noSettings = True
                primaryVisibility = 1
                finalGather = 1
                motionBlur = 0
                furRender = 1

            # change to the created layer
            pm.editRenderLayerGlobals( currentRenderLayer = renderLayerNode.name() )
            print "currentRenderLayer is : %s" % pm.editRenderLayerGlobals( query = True, currentRenderLayer = True)

            # assign all object to the layer
            pm.editRenderLayerMembers ( renderLayerNode.name(), allNodes[0], noRecurse=True )

            # override render settings
            pm.editRenderLayerAdjustment( renderLayerNode.name(), miDefaultOptions.attr('finalGather') )
            miDefaultOptions.setAttr('finalGather', finalGather )

            # override node attributes
            for node in allNodes:
                if node.type() == "mesh":
                    if len( node.primaryVisibility.inputs() ) == 0:
                        pm.editRenderLayerAdjustment( renderLayerNode.name(), node.attr('primaryVisibility') )
                        node.setAttr('primaryVisibility', primaryVisibility )

            # create pre and post render layer attributes
            self.createRenderLayerAttributes( renderLayerNode, fileRef )

            # append the render layer to the renderLayerNode list
            renderLayerNodes.append( renderLayerNode )

        if not isLoaded:
            fileRef.unload()

        return renderLayerNodes

    def createRenderLayerAttributes(self, renderLayerNode , fileRefNode ):
        assert( isinstance(renderLayerNode,pm.RenderLayer))
        assert( isinstance(fileRefNode,pm.FileReference))

        # create attributes
        renderLayerNode.addAttr( "preRenderString", dt = "string", k = True )
        renderLayerNode.addAttr( "postRenderString", dt = "string", k = True )

        # create MEL commands and set to the appropriate attribute
        refCommonCommand = fileRefNode.refNode.name() + '" "' + fileRefNode.path + '"'
        loadRefCmd = 'file -loadReference "' + refCommonCommand + ";"
        unloadRefCmd = 'file -unloadReference "' + refCommonCommand + ";"

        renderLayerNode.setAttr("preRenderString", loadRefCmd, type = "string")
        renderLayerNode.setAttr("postRenderString", unloadRefCmd, type = "string")


    def setupRenderMelSettings(self):
        defaultRenderGlobals = pm.PyNode('defaultRenderGlobals')
        defaultRenderGlobals.setAttr('preRenderLayerMel','oyEvalRenderLayerSpecificScript("pre");')
        defaultRenderGlobals.setAttr('postRenderLayerMel','oyEvalRenderLayerSpecificScript("post");')

    def parseLayerSettings(self, layerName):
        ### return a dictionary that contains
        # layer names comes as layerName#p=0,f=1,m=1 format
        #assert( isinstance(layerName,str))

        parts = layerName.split('#')

        flagAndValueAsDict = dict()

        #print 'parts length : %s' % len(parts)
        if len(parts) > 1:
            layerName = parts[0]
            rawFlags = parts[1]
            flagValueCoupleList = rawFlags.split('|')

            for flagValueCouple in flagValueCoupleList:
                flagAndValue = flagValueCouple.split('=')
                flagAndValueAsDict[flagAndValue[0]] = flagAndValue[1]

        return flagAndValueAsDict


def collectDataAndRun():
    # get selected list
    items = pm.TextScrollList( 'oyRT_references_scrollList' ).getSelectItem()
    if items is None:
        print("Nothing is selected from the list, please select some references!")
        return

    # get raw layer list
    rawLayers = pm.TextField( 'oyRT_renderLayerNames_textField' ).getText()

    # convert to list
    renderLayers = rawLayers.split(',')

    if len(renderLayers) == 0:
        print("please write some renderLayer names")
        return

    baseName = pm.TextField( 'oyRT_baseName_textField' ).getText()

    newRef = Reference( refNodes = items, renderLayers = renderLayers, baseName = baseName )
    newRef.autoCreateRenderLayers()
    newRef.setupRenderMelSettings()


def main():
    version = "v1.0.0"
    wWidth = 410
    wHeight = 350

    # get references in the current scene
    import oyReferenceTools as oyRT

    newRef = oyRT.Reference()

    refs = newRef.getReferenceNodes();

    if pm.window( 'oyReferenceTools_Window', exists = True ):
        pm.deleteUI( 'oyReferenceTools_Window', window = True )

    pm.window( 'oyReferenceTools_Window', title = 'oyReferenceTools '+version, wh = (wWidth, wHeight) )    
    pm.columnLayout( 'oyRT_coloumnLayout1', adj = True, cat = ('both',5) )

    pm.text( 'oyRT_references_text', l = 'References', fn = 'obliqueLabelFont' )
    pm.textScrollList( 'oyRT_references_scrollList', append = refs, h = 200,  allowMultiSelection = True)

    pm.text( 'oyRT_renderLayerNames_text', l = 'Render Layer Names', fn = 'obliqueLabelFont' )
    pm.textField( 'oyRT_renderLayerNames_textField', tx = 'beauty#pv=1|fg=1|mb=0|fur=0,shadow#pv=0|fg=0|mb=0|fur=0,contactShadow#pv=0|fg=0|mb=0|fur=0,reflection#pv=0|fg=0|mb=0|fur=0' )

    pm.text( 'oyRT_baseName_text', l = 'Base Name', fn = 'obliqueLabelFont' )
    pm.textField( 'oyRT_baseName_textField', tx = 'jemBey' )

    pm.button( 'oyRT_setupLayers_button', l = 'SETUP RENDER LAYERS', bgc = (1.0,0.25,0.0) , c = 'import oyReferenceTools as oyRT; oyRT.collectDataAndRun()' )

    pm.setParent( '..' )

    pm.showWindow( 'oyReferenceTools_Window' )
    pm.window('oyReferenceTools_Window', edit = True, wh = ( wWidth, wHeight ) )

if __name__ == "__main__":
    main()




#def oyRenderLayerRenderStringEditor():

    #if pm.window( 'oyRenderLayerStringEditor_Window', exists = True ):
        #pm.deleteUI( 'oyRenderLayerStringEditor_Window', window = True )

    #pm.window( 'oyRenderLayerStringEditor_Window', title = 'oyReferenceTools '+version, wh = (wWidth, wHeight) )    
    #pm.columnLayout( 'oyRT_coloumnLayout1', adj = True, cat = ('both',5) )

    #pm.text( 'oyRT_references_text', l = 'References', fn = 'obliqueLabelFont' )
    #pm.textScrollList( 'oyRT_references_scrollList', append = refs, h = 200,  allowMultiSelection = True)

    #pm.text( 'oyRT_renderLayerNames_text', l = 'Render Layer Names', fn = 'obliqueLabelFont' )
    #pm.textField( 'oyRT_renderLayerNames_textField', tx = 'beauty#pv=1|fg=1|mb=0|fur=0,shadow#pv=0|fg=0|mb=0|fur=0,contactShadow#pv=0|fg=0|mb=0|fur=0,reflection#pv=0|fg=0|mb=0|fur=0' )

    #pm.text( 'oyRT_baseName_text', l = 'Base Name', fn = 'obliqueLabelFont' )
    #pm.textField( 'oyRT_baseName_textField', tx = 'jemBey' )

    #pm.button( 'oyRT_setupLayers_button', l = 'SETUP RENDER LAYERS', bgc = (1.0,0.25,0.0) , c = 'import oyReferenceTools as oyRT; oyRT.collectDataAndRun()' )

    #pm.setParent( '..' )

    #pm.showWindow( 'oyRenderLayerStringEditor_Window' )    
    #pm.window('oyRenderLayerStringEditor_Window', edit = True, wh = ( wWidth, wHeight ) )


def resetPrimVis():
    # re-set primary visibilities to 0 in refrence nodes by analyzing the postRenderString

    layers = pm.ls(type='renderLayer')

    miDefaultOptions = pm.PyNode('miDefaultOptions')

    #layers = (pm.RenderLayer('jemBey1_contactShadow12'),pm.RenderLayer('jemBey1_contactShadow13'))

    for layer in layers:

        if not layer.hasAttr('postRenderString'):
            continue
        else:
            print "changing %s" % layer.name()

        postRenderString = layer.getAttr('postRenderString')

        splits = postRenderString.split(' ');

        refName = splits[2][1:-1]

        #print refName	

        fileRef = pm.FileReference( refnode = refName )

        fileRef.load()

        pm.editRenderLayerGlobals( currentRenderLayer=layer.name())
        pm.editRenderLayerAdjustment( layer.name(), miDefaultOptions.attr('finalGather') )
        miDefaultOptions.setAttr('finalGather',0)

        allNodes = fileRef.nodes()

        pm.editRenderLayerMembers( layer.name(), allNodes[0] , noRecurse = True)

        for node in allNodes:
            if node.type() == "mesh":
                #print 'setting',node.name(),' primaryVisibility to 0'
                #if node.primaryVisibility.inputs() < 1:
                pm.editRenderLayerAdjustment( layer.name(), node.attr('primaryVisibility') )
                node.setAttr('primaryVisibility',0)
                #pm.editRenderLayerAdjustment( layer.name(), node.attr('primaryVisibility') )

        fileRef.unload()


def replaceReferences( refNames , newRefFilePath ):

    # get nodes from the scene
    for refName in refNames:
        refNode = pm.Reference(refName)

        fileRef = pm.FileReference( refnode = refNode )

        isLoaded = fileRef.isLoaded()        
        fileRef.replaceWith( newRefFilePath )

        if not isLoaded:
            fileRef.unload()


def rr_selectFile_buttonCommand():
    filePath = pm.fileDialog( dm='*.ma' )
    pm.TextFieldButtonGrp( 'oyRR_filePath_textFieldButtonGrp' ).setText(filePath)



def rrCollectDataAndRun():
    # get selected list
    rawRefNames = pm.TextScrollList( 'oyRR_references_scrollList' ).getSelectItem()

    if rawRefNames is None:
        print("Nothing is selected from the list, please select some references!")
        return

    newRefFilePath = pm.TextFieldButtonGrp( 'oyRR_filePath_textFieldButtonGrp' ).getText()

    replaceReferences( rawRefNames, newRefFilePath )


def replaceReferencesEditor():
    version = "v1.0.0"
    wWidth = 410
    wHeight = 350

    import oyReferenceTools as oyRT
    newRef = oyRT.Reference()
    refs = newRef.getReferenceNodes();

    if pm.window( 'oyReplaceReferences_Window', exists = True ):
        pm.deleteUI( 'oyReplaceReferences_Window', window = True )

    pm.window( 'oyReplaceReferences_Window', title = 'oyReplaceReferencesTool '+version, wh = (wWidth, wHeight) )    
    pm.columnLayout( 'oyRR_coloumnLayout1', adj = True, cat = ('both',5) )

    pm.text( 'oyRR_references_text', l = 'References', fn = 'obliqueLabelFont' )
    pm.textScrollList( 'oyRR_references_scrollList', append = refs, h = 200,  allowMultiSelection = True)

    pm.text( 'oyRR_filePath_text', l = 'Replace with', fn = 'obliqueLabelFont' )
    pm.textFieldButtonGrp( 'oyRR_filePath_textFieldButtonGrp', bl = '...', bc = 'import oyReferenceTools as oyRT;oyRT.rr_selectFile_buttonCommand()' )

    pm.button( 'oyRR_replace_button', l = 'REPLACE REFERENCES', bgc = (1.0,0.25,0.0) , c = 'import oyReferenceTools as oyRT; oyRT.rrCollectDataAndRun()' )

    pm.setParent( '..' )

    pm.showWindow( 'oyReplaceReferences_Window' )
    pm.window('oyReplaceReferences_Window', edit = True, wh = ( wWidth, wHeight ) )


def sendToSmedgeEditor():

    version = "v1.0.0"
    wWidth = 410
    wHeight = 350

    # list renderable layers    
    layers = pm.ls(type='renderLayer')

    if pm.window( 'oySendToSmedge_Window', exists = True ):
        pm.deleteUI( 'oySendToSmedge_Window', window = True )

    pm.window( 'oySendToSmedge_Window', title = 'oySendToSmedge_Window '+version, wh = (wWidth, wHeight) )    
    pm.columnLayout( 'oyRR_coloumnLayout1', adj = True, cat = ('both',5) )

    pm.text( 'oySTS_layers_text', l = 'Layers', fn = 'obliqueLabelFont' )
    pm.textScrollList( 'oySTS_layers_scrollList', append = layers, h = 200,  allowMultiSelection = True)

#    pm.text( 'oyRR_filePath_text', l = 'Replace with', fn = 'obliqueLabelFont' )
#    pm.textFieldButtonGrp( 'oyRR_filePath_textFieldButtonGrp', bl = '...', bc = 'import oyReferenceTools as oyRT;oyRT.rr_selectFile_buttonCommand()' )


    minRange = pm.playbackOptions(q=1,min=1)
    maxRange = pm.playbackOptions(q=1,max=1)

    pm.intFieldGrp( 'oySTS_range_intField' , label = 'start / end / packet' , nf=3, v=(minRange,maxRange,1,1))
    pm.intSliderGrp('oySTS_priority_intSliderGrp' , adj = 2 , fmn = 0 , fmx = 100 , f=True, fs = 1, l='priority', s=1 , v=100 )

    pm.button( 'oySTS_sendToSmedge_button', l = 'SEND TO SMEDGE', bgc = (1.0,0.25,0.0) , c = 'import oyReferenceTools as oyRT; oyRT.ssCollectDataAndRun()' )

    pm.setParent( '..' )

    pm.showWindow( 'oySendToSmedge_Window' )
    pm.window('oySendToSmedge_Window', edit = True, wh = ( wWidth, wHeight ) )


def ssCollectDataAndRun():
    # needed fields
    # +startFrame
    # +endFrame
    # +packetSize
    # +priority
    # +projectPath
    # +jobName     in   ProjectName : scenename : layerName format
    # +layerName
    # +sceneFullPath

    import os
    # startFrame
    frameData = pm.intFieldGrp('oySTS_range_intField',q=True,v=True)
    startFrame = frameData[0]
    endFrame = frameData[1]
    packetSize = frameData[2]

    priority = pm.intSliderGrp('oySTS_priority_intSliderGrp',q=True,v=True)

    projectPath = os.path.realpath( pm.workspace.path )
    sceneFullPath = os.path.realpath( pm.sceneName() )

    projectName = projectPath.split(os.path.sep)[-1]    
    sceneName = sceneFullPath.split(os.path.sep)[-1]


    layers = pm.TextScrollList( 'oySTS_layers_scrollList' ).getSelectItem()

    keys = dict()
    keys['startFrame'] = startFrame
    keys['endFrame'] = endFrame
    keys['packetSize'] = packetSize
    keys['priority'] = priority
    keys['projectPath'] = projectPath
    keys['sceneFullPath'] = sceneFullPath

    for layer in layers:
        keys['layerName'] = layer
        keys['jobName'] = projectName + ' : ' + sceneName + ' : ' + layer

        layerNode = pm.RenderLayer(layer)
        if layerNode.hasAttr('renderRangeMin'):
            layerMin = layerNode.getAttr('renderRangeMin')
            if layerMin > startFrame:
                keys['startFrame'] = layerNode.getAttr('renderRangeMin')
            else:
                keys['startFrame'] = startFrame
        else:
            keys['startFrame'] = startFrame


        if layerNode.hasAttr('renderRangeMax'):
            layerMax = layerNode.getAttr('renderRangeMax')
            if layerMax < endFrame:
                keys['endFrame'] = layerNode.getAttr('renderRangeMax')
            else:
                keys['endFrame'] = endFrame
        else:
            keys['endFrame'] = endFrame


        sendToSmedge( **keys )



def sendToSmedge( **keys ):

    

    # get the information needed by smedge
    smrFile = createSmrFile( keys )
    import os

    progFilesDir = ''

    if os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64':
        progFilesDir ='C:\Program Files (x86)'
    else:
        progFilesDir ='C:\Program Files'

    command = r'"'+progFilesDir+'\Smedge\smedge.exe" -submit ' + smrFile
    #$command = $programsFolder + "Smedge\\smedge.exe\" -submit " + toNativePath( "\"" + $smedgeFileFullPath + "\"" );

    print command
    import os
    os.system( command )


def createSmrFile( keys ):

    smrFilePath = keys['sceneFullPath'] + '.smr' 
    print 'smrFilePath : %s' % smrFilePath
    smrFile = open( smrFilePath, 'w' )

    smrFileContent = [""]
    smrFileContent.append( r'End = ' + str(keys['endFrame']) +'\n')
    smrFileContent.append( r'ExtraParameters = -preRender oyRenderOneLayer(\"' + keys['layerName'] + r'\")' +'\n')
    smrFileContent.append( r'ImageDir = '+'\n')
    smrFileContent.append( r'ImageFmt = '+'\n')
    smrFileContent.append( r'JobName = ' + keys['jobName'] +'\n')
    smrFileContent.append( r'KillOvertime = 1200' +'\n')
    smrFileContent.append( r'MaxCPUs = -1' +'\n')
    smrFileContent.append( r'MultiThread = 1' +'\n')
    smrFileContent.append( r'Note = Created with oyReferenceTools v1.0.0' +'\n')
    smrFileContent.append( r'OutputDir = ' +'\n')
    smrFileContent.append( r'Packet = ' + str(keys['packetSize']) +'\n')
    smrFileContent.append( r'Pool = Whole System' +'\n')
    smrFileContent.append( r'Priority = ' + str(keys['priority']) +'\n')
    smrFileContent.append( r'Product = MentalRayForMaya' +'\n')
    smrFileContent.append( r'Project = ' + keys['projectPath'] +'\n')
    smrFileContent.append( r'SceneName = ' + keys['sceneFullPath'] +'\n')
    smrFileContent.append( r'Start = ' + str(keys['startFrame']) +'\n')

    smrFile.writelines( smrFileContent )
    smrFile.close()

    return smrFilePath




















